<template>
	<div class="page">
		<div class="p-10 system-page-background b-r-4">
			<my-form
				inline
				query
				label-width="70px"
				:model="queryParams"
				:formItem="queryFormItem"
				:searchFn="() => refTable.reload()"
			/>
		</div>
		<div class="f1 h0 flex-col m-t-10 system-page-background b-r-4">
			<div class="p-10" v-hasPermi="['system:role:add', 'system:role:remove', 'system:role:export']">
				<el-button type="primary" icon="Plus" @click.prevent="Add" v-hasPermi="['system:role:add']">新增</el-button>
				<el-button-group>
					<my-button-export :load="Export" v-hasPermi="['system:role:export']" />
				</el-button-group>
				<el-button
					type="danger"
					:disabled="!tableSelection.length"
					@click.prevent="deleteFn(tableSelection)"
					icon="Delete"
					v-hasPermi="['system:role:remove']"
				>
					删除
				</el-button>
			</div>
			<my-list-panel ref="refTable" :loadFn="loadData" :total="state.total">
				<my-table :data="state.list" :columns="state.columns" @selection-change="(val) => (tableSelection = val)">
					<template #status="{ row }">
						<el-switch
							v-model="row.status"
							inline-prompt
							:active-value="0"
							:inactive-value="1"
							active-text="启"
							inactive-text="停"
							@change="StatusChange(row)"
						></el-switch>
					</template>
					<template #default="{ row }">
						<my-button-text @click="Update(row)" v-hasPermi="['system:role:edit']">修改</my-button-text>
						<my-button-text @click="DataScope(row)" v-hasPermi="['system:role:data']">数据权限</my-button-text>
						<my-button-text @click="moduleScope(row)" v-hasPermi="['system:role:data']">组件权限</my-button-text>
					</template>
				</my-table>
			</my-list-panel>
		</div>

		<!-- 添加或修改角色配置对话框 -->
		<el-dialog
			:title="dialog.title"
			v-model="dialog.open"
			width="600px"
			append-to-body
			@closed="resetForm(refDialogForm)"
		>
			<el-form
				ref="refDialogForm"
				:model="dialog.form"
				:rules="rules"
				label-width="80px"
				class="validate--bottom dialog-form"
			>
				<el-form-item label="角色名称" prop="roleName">
					<my-input v-model="dialog.form.roleName" placeholder="请输入角色名称" />
				</el-form-item>
				<el-form-item label="权限字符" prop="roleKey">
					<my-input v-model="dialog.form.roleKey" placeholder="请输入权限字符" />
				</el-form-item>
				<el-form-item label="角色顺序" prop="roleSort">
					<my-input-number v-model="dialog.form.roleSort" :min="0" :maxlength="10" numberType="init" />
				</el-form-item>
				<el-form-item label="状态" prop="status">
					<el-radio-group v-model="dialog.form.status">
						<el-radio v-for="dict in $store.dict.sysNormalDisable" :key="dict.dictValue" :label="dict.dictValue * 1">{{
							dict.dictLabel
						}}</el-radio>
					</el-radio-group>
				</el-form-item>
				<el-form-item label="菜单数据">
					<el-checkbox v-model="dialog.menuExpand" @change="CheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
					<el-checkbox v-model="dialog.menuNodeAll" @change="CheckedTreeNodeAll($event, 'menu')"
						>全选/全不选</el-checkbox
					>
					<!-- <el-checkbox v-model="dialog.form.menuStrictly" :true-label="1" :false-label="0">父子联动</el-checkbox> -->
					<el-tree
						accordion
						class="tree-border overflow-y-auto"
						:data="menuOptions"
						show-checkbox
						ref="refMenu"
						node-key="id"
						:check-strictly="!dialog.form.menuStrictly"
						empty-text="加载中，请稍后"
						:props="{ children: 'children', label: 'menuName' }"
						style="min-height: 100px; max-height: 250px"
					/>
				</el-form-item>
				<el-form-item label="备注">
					<my-input v-model="dialog.form.remark" type="textarea" placeholder="请输入内容" />
				</el-form-item>
			</el-form>
			<template #footer>
				<el-button @click="cancel">取消</el-button>
				<el-button type="primary" @click="submitForm()">确定</el-button>
			</template>
		</el-dialog>

		<!-- 角色数据权限对话框 -->
		<el-dialog :title="dialog.title" v-model="dialog.openDataScope" width="600px" append-to-body>
			<el-form :model="dialog.form" label-width="70px" class="validate--bottom dialog-form">
				<el-form-item label="角色名称">
					<my-input v-model="dialog.form.roleName" disabled />
				</el-form-item>
				<el-form-item label="权限字符">
					<my-input v-model="dialog.form.roleKey" disabled />
				</el-form-item>
				<el-form-item label="权限范围">
					<el-select v-model="dialog.form.dataScope">
						<el-option
							v-for="item in dataScopeOptions"
							:key="item.value"
							:label="item.label"
							:value="item.value"
						></el-option>
					</el-select>
				</el-form-item>
				<el-form-item label="数据权限" v-show="dialog.form.dataScope == 2">
					<el-checkbox v-model="dialog.deptExpand" @change="CheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
					<el-checkbox v-model="dialog.deptNodeAll" @change="CheckedTreeNodeAll($event, 'dept')"
						>全选/全不选</el-checkbox
					>
					<el-checkbox v-model="dialog.form.deptStrictly" :true-label="1" :false-label="0">父子联动</el-checkbox>
					<el-tree
						accordion
						class="tree-border overflow-y-auto"
						:data="deptOptions"
						show-checkbox
						default-expand-all
						ref="refDept"
						node-key="id"
						:check-strictly="!dialog.form.deptStrictly"
						empty-text="加载中，请稍后"
						:props="{ children: 'children', label: 'deptName' }"
						style="min-height: 100px; max-height: 150px"
					/>
				</el-form-item>
			</el-form>
			<template #footer>
				<el-button @click="cancelDataScope">取消</el-button>
				<el-button type="primary" @click="submitDataScope()">确定</el-button>
			</template>
		</el-dialog>

		<!-- 角色组件权限 -->
		<el-dialog title="组件权限" v-model="dialog2.open" width="600px" append-to-body @closed="resetForm(refDialogForm2)">
			<my-form
				ref="refDialogForm2"
				:model="dialog2.form"
				label-width="90px"
				:disabled="['detail'].includes(dialog2.name)"
				:formItem="[
					{ prop: 'roleName', label: '角色名称', disabled: true },
					{ prop: 'roleKey', label: '权限字符', disabled: true },
					{
						itemType: 'select',
						prop: 'moduleIds',
						label: '组件权限',
						required: true
					}
				]"
			>
				<template #moduleIds="{ model, prop }">
					<my-select
						v-model="model[prop]"
						collapse-tags-tooltip
						collapse-tags
						clearable
						filterable
						multiple
						@change="selectChange"
						placeholder="请选择组件权限"
					>
						<el-option
							v-for="item in versionList"
							:key="item.id"
							:label="item.title"
							:value="item.id"
							:disabled="item.disabled"
						>
							<span style="float: left">{{ item.title }}</span>
							<span style="float: right; font-size: 12px">{{ item.version }}</span>
						</el-option>
					</my-select>
				</template>
			</my-form>
			<template #footer>
				<el-button @click.prevent="dialog2.open = false">取 消</el-button>
				<el-button type="primary" @click.prevent="dialogSubmitFn()">确 定</el-button>
			</template>
		</el-dialog>
	</div>
</template>

<script setup name="/system/role">
import { pageRole, removeRole, addRole, editRole, infoRole, exportRole, roleModule } from '@/api/system';
import { changeRoleStatus, changeDataPerm, getRoleMenuList, getRoleDeptList } from '@/api/public';
import { moduleVersionList } from '@/api/module';
import { downloadBlob } from '@u/download';

const dataScopeOptions = [
		{
			value: 1,
			label: '全部数据权限'
		},
		{
			value: 2,
			label: '自定数据权限'
		},
		{
			value: 3,
			label: '本部门数据权限'
		},
		{
			value: 4,
			label: '本部门及以下数据权限'
		},
		{
			value: 5,
			label: '仅本人数据权限'
		}
	],
	rules = {
		roleName: [{ required: true, message: '角色名称不能为空', trigger: 'change' }],
		roleKey: [{ required: true, message: '权限字符不能为空', trigger: 'change' }],
		roleSort: [{ required: true, message: '角色顺序不能为空', trigger: 'change' }]
	};

/**************************表格逻辑***************************** */
const queryFormItem = [
		{ prop: 'likeRoleName', label: '角色名称' },
		{ prop: 'likeRoleKey', label: '权限字符' },
		{
			itemType: 'select',
			prop: 'status',
			label: '状态',
			list: $store.dict.sysNormalDisable
		},
		{
			itemType: 'date',
			prop: 'dateRange',
			label: '创建时间',
			type: 'datetimerange',
			rangeSeparator: '至',
			startPlaceholder: '开始日期',
			endPlaceholder: '结束日期',
			prepend: 'CreateTime'
		}
	],
	columns = [
		{
			type: 'selection'
		},
		{
			label: '角色编号',
			prop: 'id',
			align: 'center'
		},
		{
			label: '角色名称',
			prop: 'roleName',
			align: 'center'
		},
		{
			label: '权限字符',
			prop: 'roleKey',
			align: 'center'
		},
		{
			label: '显示顺序',
			prop: 'roleSort',
			align: 'center'
		},
		{
			label: '状态',
			prop: 'status',
			align: 'center'
		},
		{
			label: '创建时间',
			prop: 'createTime',
			align: 'center',
			width: 160
		},
		{
			label: '操作',
			align: 'center',
			width: 220
		}
	],
	{ queryParams, refTable, state, tableSelection, getList, loadData, deleteFn, dialog, refDialogForm } = pageMixin({
		queryFormItem,
		queryParamsDefault: {
			orderByColumn: 'roleSort',
			isAsc: 'asc'
		},
		columns,
		api: { page: pageRole, remove: removeRole },
		dialogDefault: {
			title: '',
			// 角色弹窗
			open: false,
			form: {
				id: undefined,
				roleName: '',
				roleKey: '',
				roleSort: 0,
				status: 0,
				menuIds: [],
				deptIds: [],
				menuStrictly: 1,
				deptStrictly: 1,
				remark: ''
			},
			// 是否显示弹出层（数据权限）
			openDataScope: false,
			menuExpand: false,
			menuNodeAll: false,
			deptExpand: true,
			deptNodeAll: false
		}
	});

// 取消按钮
function cancel() {
	dialog.open = false;
	dialog.menuExpand = false;
	dialog.menuNodeAll = false;
	dialog.deptExpand = true;
	dialog.deptNodeAll = false;
}
/** 新增按钮操作 */
function Add() {
	resetForm(refDialogForm);
	getMenuTreeselect();
	dialog.open = true;
	dialog.title = '添加角色';
	dialog.form.id = undefined;
	nextTick(() => {
		refMenu.value.setCheckedKeys([]);
	});
}
/** 修改按钮操作 */
function Update(row) {
	const roleId = row.id;
	const roleTreeInfo = getRoleMenuTreeselect(roleId);
	infoRole({ id: row.id }).then((res) => {
		dialog.open = true;
		dialog.title = '修改角色';
		nextTick(() => {
			dialog.form = res.data;
			roleTreeInfo.then((res) => {
				res.data.ruleMenuIds.forEach((item) => {
					const node = refMenu.value.getNode(item);
					// 过滤掉不是叶子节点的数据
					if (node.isLeaf) refMenu.value.setChecked(node, true);
				});
			});
		});
	});
}
/** 提交按钮 */
function submitForm() {
	refDialogForm.value.validate((valid) => {
		if (valid) {
			dialog.form.menuIds = getMenuAllCheckedKeys();
			if (dialog.form.id != undefined) {
				editRole(dialog.form).then(() => {
					msgSuccess('修改成功');
					cancel();
					getList();
				});
			} else {
				addRole(dialog.form).then(() => {
					msgSuccess('新增成功');
					cancel();
					getList();
				});
			}
		}
	});
}
/**
 * 启用、停用
 * @param {Object} row 行数据
 */
function StatusChange(row) {
	if (row.id) {
		const text = row.status === 0 ? '启用' : '停用';
		confirm({ item: `确认要—${text}（${row.roleName}）角色吗?` })
			.then(() => changeRoleStatus({ id: row.id, status: row.status }))
			.then(() => {
				msgSuccess(text + '成功');
			})
			.catch(function () {
				row.status = row.status === 0 ? 1 : 0;
				msgInfo('已取消！');
			});
	}
}
/** 导出按钮操作 */
function Export() {
	return exportRole(queryParams).then((data) => {
		downloadBlob(data, '角色管理.xlsx');
	});
}
$store.dict.GETsysNormalDisable();

/**************************************数据权限逻辑************************************** */
const menuOptions = ref([]),
	deptOptions = ref([]);
const refMenu = shallowRef(null),
	refDept = shallowRef(null);
/** 查询菜单树结构 */
function getMenuTreeselect() {
	getRoleMenuList().then((res) => {
		menuOptions.value = res.data.menus;
	});
}
/** 根据角色ID查询菜单树结构 */
function getRoleMenuTreeselect(roleId) {
	return getRoleMenuList({ roleId: roleId }).then((res) => {
		menuOptions.value = res.data.menus;
		return res;
	});
}
// 所有菜单节点数据
function getMenuAllCheckedKeys() {
	// 目前被选中的菜单节点
	const checkedKeys = refMenu.value.getCheckedKeys();
	// 半选中的菜单节点
	const halfCheckedKeys = refMenu.value.getHalfCheckedKeys();
	checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
	return checkedKeys;
}
// 所有部门节点数据
function getDeptAllCheckedKeys() {
	// 目前被选中的部门节点
	const checkedKeys = refDept.value.getCheckedKeys();
	// 半选中的部门节点
	const halfCheckedKeys = refDept.value.getHalfCheckedKeys();
	checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
	return checkedKeys;
}
// 取消按钮（数据权限）
function cancelDataScope() {
	dialog.openDataScope = false;
	dialog.menuExpand = false;
	dialog.menuNodeAll = false;
	dialog.deptExpand = true;
	dialog.deptNodeAll = false;
}
// 树权限（展开/折叠）
function CheckedTreeExpand(value, type) {
	if (type == 'menu') {
		const treeList = menuOptions.value;
		for (let i = 0; i < treeList.length; i++) {
			refMenu.value.store.nodesMap[treeList[i].id].expanded = value;
		}
	} else if (type == 'dept') {
		const treeList = deptOptions.value;
		for (let i = 0; i < treeList.length; i++) {
			refDept.value.store.nodesMap[treeList[i].id].expanded = value;
		}
	}
}
// 树权限（全选/全不选）
function CheckedTreeNodeAll(value, type) {
	if (type == 'menu') {
		nextTick(() => {
			refMenu.value.setCheckedNodes(value ? menuOptions.value : []);
		});
	} else if (type == 'dept') {
		nextTick(() => {
			refDept.value.setCheckedNodes(value ? deptOptions.value : []);
		});
	}
}
/**数据权限操作 */
function DataScope(row) {
	const roleDeptTreeselect = getRoleDeptTreeselect(row.id);
	infoRole({ id: row.id }).then((res) => {
		dialog.openDataScope = true;
		nextTick(() => {
			dialog.form = res.data;
			roleDeptTreeselect.then((res) => {
				res.data.ruleDeptIds.forEach((item) => {
					const node = refDept.value.getNode(item);
					// 过滤掉不是叶子节点的数据
					if (node.isLeaf) refDept.value.setChecked(node);
				});
			});
		});
		dialog.title = '数据权限';
	});
}
/** 根据角色ID查询部门结构 */
function getRoleDeptTreeselect(roleId) {
	return getRoleDeptList({ roleId: roleId }).then((res) => {
		deptOptions.value = res.data.depts;
		return res;
	});
}
/** 提交按钮（数据权限） */
function submitDataScope() {
	if (dialog.form.id != undefined) {
		dialog.form.deptIds = getDeptAllCheckedKeys();
		changeDataPerm(dialog.form).then(() => {
			msgSuccess('修改成功');
			cancelDataScope();
			getList();
		});
	}
}

/**************************组件权限逻辑***************************** */
const { dialog: dialog2, refDialogForm: refDialogForm2 } = pageMixin({
		dialogDefault: {
			// 角色弹窗
			open: false,
			form: {
				id: undefined
			}
		}
	}),
	versionList = ref([]);

// 打开弹窗，获取 `组件-版本` 数据
function moduleScope(row) {
	dialog2.open = true;
	moduleVersionList({ sysRoleId: row.id }).then((res) => {
		versionList.value = res.data;
		dialog2.form.moduleIds = res.data.filter((item) => !!item.isSelected).map((item) => item.id) || [];
	});
	nextTick(() => {
		dialog2.form.roleName = row.roleName;
		dialog2.form.roleKey = row.roleKey;
		dialog2.form.sysRoleId = row.id;
	});
}
// 相关组件只能选择一个版本
function selectChange(value) {
	versionList.value.forEach((item) => (item.disabled = false));
	value.forEach((val) => {
		const xvueNameSpace = versionList.value.find((item) => item.id === val).xvueNameSpace;
		versionList.value.forEach((item) => {
			if (item.id !== val && item.xvueNameSpace === xvueNameSpace) item.disabled = true;
		});
	});
}
function dialogSubmitFn() {
	const DialogForm = unref(refDialogForm2),
		Form = DialogForm?.$refs?.refMyForm || DialogForm;
	Form.validate((valid) => {
		if (valid) {
			roleModule(dialog2.form).then(() => {
				msgSuccess('操作成功！');
				dialog2.open = false;
				getList();
			});
		}
	});
}
</script>

<style lang="scss" scoped>
.tree-border {
	margin-top: 5px;
	border: 1px solid #e5e6e7;
	border-radius: 4px;
}
.dialog-form :deep(.el-form-item__content) {
	display: block;
}
</style>
